﻿// Inner Fire 游戏引擎库
// static_string 静态字符串
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 一种string_view的改进版本。通过一个字符串内存池来控制字符串。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-03-16

#include "static_string.h"
#include <EASTL/string_view.h>
#include <EASTL/unordered_map.h>
#include <Windows.h>
#include <klog.h>
#include <kstring.h>
#include <string.h>
#include <unordered_map>

namespace ikit {
eastl::unordered_map<eastl::string_view, static_string_instance> string_map;
static_string_manager manager(1024 * 1024);

sstr::sstr(const char* text) {
  // 特殊检查，空指针或是第一位就是0的字符串
  if (text == nullptr || text[0] == '\0'){
    uid_ = 0;
  }else{
    uid_ = static_string_instance(text).uid;
  }
}

sstr::sstr(const char* text, size_t len)
    : uid_(static_string_instance(text, len).uid) {}

const char* sstr::c_str() const { return manager.get_chars(*this); }

size_t sstr::size() const { return manager.get_instance(uid_).size; }

int sstr::index_of(char c) const {
  // 常规检查
  if (empty()) {
    return -1;
  }
  // 得到实例
  auto& s = manager.get_instance(uid_);
  // 检查符号
  for (size_t i = 0; i < s.size; i++) {
    if (s.pointer[i] == c) {
      return static_cast<int>(i);
    }
  }
  return -1;
}

int sstr::index_of(const char* substr) const {
  const char* text = c_str();
  const char* pos = strstr(text, substr);
  return pos ? (int)(pos - text) : -1;
}

sstr sstr::substr(size_t begin, size_t count) const {
  // 常规检查
  if (empty()) {
    return *this;
  }

  // 得到实例
  auto& s = manager.get_instance(uid_);

  // 判断合法性
  assert(!(begin < 0 || begin >= s.size));

  // 如果count=0，则表示裁剪到尾部，需要计算位置
  if (count == 0) {
    count = s.size - begin;
  }
  // 判断裁剪范围合法性
  assert(begin + count <= s.size);

  // 根据截取的部分，创造一个项目
  return sstr(s.pointer + begin, count);
}

std::wstring sstr::to_wide() const { return ikit::to_wide(c_str()); }

std::string sstr::gbk() const { return ikit::utf8_to_gbk(c_str()); }

sstr get_string_uid(const char* text) {
  return static_string_instance(text).uid;
}

const char* get_chars(sstr uid) { return manager.get_chars(uid); }

std::string get_chars_to_gbk(sstr uid) {
  auto chars = get_chars(uid);
  return ikit::utf8_to_gbk(chars);
}

// 从一个列表中读取项目，每一个项目使用","号分割。不支持Trim，所以","号之间不能有任何空格。
eastl::vector<sstr> get_string_list(const char* text) {
  eastl::vector<sstr> result;
  if (!text || *text == '\0') {
    return result; // 空输入返回空列表
  }

  const char* start = text; // 当前子串的起始位置
  const char* end = text;   // 当前扫描位置

  while (*end != '\0') {
    if (*end == ',') {
      // 找到逗号，构造 sstr 并添加到结果
      result.emplace_back(start, end - start);
      start = end + 1; // 下一个子串的起始位置
    }
    ++end;
  }

  // 添加最后一个子串（或唯一子串，如果没有逗号）
  result.emplace_back(start, end - start);

  return result;
}

void get_name_value(const char* text, sstr& name, sstr& value) {
  const char* colon = strchr(text, ':');

  if (colon == nullptr) {
    // 没有冒号，整个字符串都是name，value为空
    name = sstr(text);
    value = sstr();
  } else {
    // 有冒号，分割name和value
    size_t name_len = colon - text;
    name = sstr(text, name_len);

    const char* value_start = colon + 1;
    size_t value_len = strlen(value_start);
    value = sstr(value_start, value_len);
  }
}

static_string_instance::static_string_instance(const char* text) {
  set_by_string_view(eastl::string_view(text));
}

static_string_instance::static_string_instance(const char* text, size_t len) {
  set_by_string_view(eastl::string_view(text, len));
}

static_string_instance::static_string_instance(const eastl::string_view& text) {
  set_by_string_view(text);
}

static_string_instance::static_string_instance(
    size_t _uid, const char* _pointer, size_t _size)
    : uid(_uid), pointer(_pointer), size(_size) {}

void static_string_instance::set_by_string_view(
    const eastl::string_view& text) {
  // 查找现有字符串
  auto it = string_map.find(text);
  if (it != string_map.end()) {
    // 复制现有实例
    uid = it->second.uid;
    size = it->second.size;
    pointer = it->second.pointer;
  } else {
    static_string_instance t = manager.create(text.data(), text.size());
    uid = t.uid;
    size = t.size;
    pointer = t.pointer;
  }
}

static_string_manager::static_string_manager(int buffer_size)
    : buffer_size_(buffer_size), uid_record(1) {
  // 直接填入一个新的BUFF
  create_new_buffer();

  // UID是从1开始，位于0位置的是一个空字符串
  strings_.emplace_back(0, EMPTY_TEXT, 0);
}

static_string_manager::~static_string_manager() {
  // 遍历项目，依次删除
  for (size_t i = 0; i < buffers_.size(); i++) {
    delete[] buffers_[i];
  }
}

static_string_instance static_string_manager::create(const char* text) {
  return create(text, strlen(text));
}

static_string_instance static_string_manager::create(
    const char* text, size_t len) {
  // 检查项目是否足够，如果不足，扩展新项目
  size_t left = buffer_size_ - current_pointer_;
  if (left < len + 1) {
    create_new_buffer();
  }

  // 复制项目到当前
  memcpy(&current_buffer_[current_pointer_], text, len);

  // 配置字符串项目
  static_string_instance s(
      uid_record++, &current_buffer_[current_pointer_], len);

  // 将项目插入
  string_map.emplace(eastl::string_view(s.pointer), s);
  strings_.push_back(s);

  // 步进项目指针
  current_pointer_ += len + 1;

  // 返回项目
  return s;
}

const char* static_string_manager::get_chars(sstr uid) const {
  // 边界检查
  if (uid.uid_ < 0 || uid.uid_ >= uid_record) {
    return EMPTY_TEXT;
  }

  return strings_[uid.uid_].pointer;
}

const static_string_instance& static_string_manager::get_instance(
    size_t uid) const {
  return strings_[uid];
}

void static_string_manager::create_new_buffer() {
  current_buffer_ = new char[buffer_size_];
  memset(current_buffer_, 0, buffer_size_);
  current_pointer_ = 0;
  buffers_.push_back(current_buffer_);
}

} // namespace ikit